
package com.yami.shop.listener;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.enums.RemindStatusEnum;
import com.yami.shop.bean.enums.RemindType;
import com.yami.shop.bean.enums.SendType;
import com.yami.shop.bean.event.SendMessageEvent;
import com.yami.shop.bean.event.SendPersonMessageEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.NotifyTemplateParam;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.util.Json;
import com.yami.shop.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.*;


/**
 * 统一发送通知的事件
 *
 * @author yami
 */
@Slf4j
@Component("sendMessageListener")
@AllArgsConstructor
public class SendMessageListener {

    private final NotifyLogService notifyLogService;

    private final NotifyTemplateService notifyTemplateService;

    private final ShopDetailService shopDetailService;


    private final UserService userService;
    private final NotifyTemplateRemindService notifyTemplateRemindService;
    private final UserSecurityConfigService userSecurityConfigService;
    @EventListener(SendMessageEvent.class)
    public void sendMsgEvent(SendMessageEvent event) {
        NotifyTemplateParam param = event.getParam();
        if (Objects.isNull(param)) {
            return;
        }
        ShopDetail shopDetail = shopDetailService.getById(param.getShopId());
        //获取模板的发送方式，获取商家选择的发送方式
        NotifyTemplate template = notifyTemplateService.getOne(new LambdaQueryWrapper<NotifyTemplate>().eq(NotifyTemplate::getSendType, param.getSendType()));
        if (Objects.isNull(template) || Objects.isNull(shopDetail)) {
            return;
        }
        //是否开启消息提醒
        Boolean notifyLogStatus = false;
        NotifyTemplateRemind notifyTemplateRemind = notifyTemplateRemindService.getOne(new LambdaQueryWrapper<NotifyTemplateRemind>()
                .eq(NotifyTemplateRemind::getTemplateId, template.getTemplateId())
                .eq(NotifyTemplateRemind::getShopId, shopDetail.getShopId())
        );
        //关闭消息提醒 则生不成消息记录
        if(Objects.nonNull(notifyTemplateRemind) && Objects.equals(notifyTemplateRemind.getIsRemind(), RemindStatusEnum.CLOSED.value())){
            notifyLogStatus = true;
        }
        String shopName = Objects.isNull(shopDetail.getShopName()) ? "商城" : shopDetail.getShopName();
        param.setShopName(shopName);
        // 截取字符串,处理过长商品名称
        if (StrUtil.isNotBlank(param.getProdName())) {
            if (Objects.equals(param.getProdName().substring(param.getProdName().length()-1),StrUtil.SPACE)){
                param.setProdName(param.getProdName().substring(0, Math.min(14, param.getProdName().length() - 1)) + "等商品");
            } else {
                param.setProdName(param.getProdName().substring(0, Math.min(14, param.getProdName().length())) + "等商品");
            }
        }
        param.setGroupCount(Objects.isNull(param.getGroupCount()) ? 0 : param.getGroupCount());
        param.setPrice(Objects.isNull(param.getPrice()) ? 0.0 : param.getPrice());
        param.setPayType(Objects.isNull(param.getPayType()) ? 1 : param.getPayType());
        param.setDvyTime(Objects.isNull(param.getDvyTime()) ? new Date() : param.getDvyTime());
        param.setProdName(Objects.isNull(param.getProdName()) ? null : param.getProdName());
        String openId = "";
        if (StrUtil.isNotBlank(param.getUserId())) {
            // 截取字符串,处理过长名称
            User user = userService.getUserDetail(param.getUserId());
            if (Objects.nonNull(user)) {
                if (CollectionUtils.isNotEmpty(user.getBizUserIdList())) {
                    openId = user.getBizUserIdList().get(0);
                }
                param.setNickName(user.getNickName().substring(0, Math.min(19, user.getNickName().length())));
            }
        }
        param.setOpenId(openId);
        // 设置平台的消息通知类型
        List<String> notifies = Arrays.asList(template.getTemplateTypes().split(StrUtil.COMMA));
        for (String notify : notifies) {
            template.setSms(StrUtil.equals(notify, "1") || template.getSms());
            template.setSub(StrUtil.equals(notify,"2") || template.getSub());
            template.setApp(StrUtil.equals(notify,"3") || template.getApp());
        }
        // 获取对应map
        Map<String, String> smsParam = getSmsParam(param);
        String content = replaceContent(smsParam, template.getMessage());
        // 保存的通知集合
        List<NotifyLog> notifyLogs = new ArrayList<>();
        if (template.getSms() && BooleanUtils.isFalse(notifyLogStatus)) {
            SendType sendTypeEnum = SendType.instance(template.getSendType());
            if(Objects.nonNull(sendTypeEnum) && Objects.equals(sendTypeEnum.getType(),SendType.RECEIPT_ORDER.getType()) && StrUtil.isBlank(param.getUserMobile())){
                log.warn(shopDetail.getShopName() +"店铺暂未配置接收通知的手机号，无法推送消息");
                return;
            }
//            Boolean isRead = smsLogService.sendMsgSms(template, param.getUser().getUserMobile(), smsParam);
            // 替换消息内容
            addNotifyLog(param, content, template, false, RemindType.SMS.value(), notifyLogs,param.getOrderNumber());
        }
        //站内消息
        if (template.getApp() && BooleanUtils.isFalse(notifyLogStatus)) {
            addNotifyLog(param, content, template, notifyLogStatus,  RemindType.MINI.value(), notifyLogs, param.getOrderNumber());
        }
        // 公众号
        if (template.getSub() && StrUtil.isNotBlank(openId) && BooleanUtils.isFalse(notifyLogStatus)) {
            addNotifyLog(param, content, template, false,  RemindType.MP.value(), notifyLogs,param.getOrderNumber());
        }

        if (CollectionUtils.isNotEmpty(notifyLogs)) {
            notifyLogService.saveBatch(notifyLogs);
        }
    }
    
    
    @EventListener(SendPersonMessageEvent.class)
    public void sendPersonMsgEvent(SendPersonMessageEvent event) throws Exception {
        NotifyTemplateParam param = event.getParam();
        if (Objects.isNull(param)) {
            return;
        }
        //获取模板的发送方式，获取商家选择的发送方式
        NotifyTemplate template = notifyTemplateService.getOne(new LambdaQueryWrapper<NotifyTemplate>().eq(NotifyTemplate::getSendType, param.getSendType()));
        if (Objects.isNull(template)) {
            return;
        }
        //是否开启消息提醒
        Boolean notifyLogStatus = false;
        if (StrUtil.isNotBlank(param.getUserId())) {
            // 截取字符串,处理过长名称
            User user = userService.getUserDetail(param.getUserId());
            if (Objects.nonNull(user)) {
                param.setNickName(user.getNickName().substring(0, Math.min(19, user.getNickName().length())));
                param.setUserMobile(user.getUserMobile());
            }
            UserSecurityConfig userSecurityConfig = userSecurityConfigService.getOne(new LambdaQueryWrapper<UserSecurityConfig>().eq(UserSecurityConfig::getUserId, param.getUserId()));
            //0开1关
            if("1".equals(userSecurityConfig.getMessageNotification())){
                if (Objects.isNull(param.getType())) {
                    notifyLogStatus = true;
                } else if("1".equals(userSecurityConfig.getLikeNotificationSwitch())&&2==param.getType()){
                    notifyLogStatus = true; //点赞通知
                } else if("1".equals(userSecurityConfig.getFollowNotificationSwitch())&&4==param.getType()){
                    notifyLogStatus = true; //关注通知
                } else if("1".equals(userSecurityConfig.getCommentNotificationSwitch())&&1==param.getType()){
                    notifyLogStatus = true; //评论通知
                } else if("1".equals(userSecurityConfig.getCollectionNotificationSwitch())&&3==param.getType()){
                    notifyLogStatus = true; //收藏通知
                }
            }
            
        }
        if (StrUtil.isNotBlank(param.getFromUserId())) {
            User user = userService.getUserDetail(param.getFromUserId());
            if (Objects.nonNull(user)) {
                param.setFromUserName(user.getNickName().substring(0, Math.min(19, user.getNickName().length())));
            }
        }
        // 设置平台的消息通知类型
        List<String> notifies = Arrays.asList(template.getTemplateTypes().split(StrUtil.COMMA));
        for (String notify : notifies) {
            template.setSms(StrUtil.equals(notify, "1") || template.getSms());
            template.setSub(StrUtil.equals(notify,"2") || template.getSub());
            template.setApp(StrUtil.equals(notify,"3") || template.getApp());
        }
        Map<String, String> stringObjectMap = getSmsParamPerson(param);
        // 获取对应map
        String content = replaceContent(stringObjectMap, template.getMessage());
        // 保存的通知集合
        List<NotifyLog> notifyLogs = new ArrayList<>();
        //站内消息
        if (template.getApp()) {
            addNotifyLog(param, content, template, notifyLogStatus,  RemindType.MINI.value(), notifyLogs,param.getOrderNumber());
        }
        if (CollectionUtils.isNotEmpty(notifyLogs)) {
            notifyLogService.saveBatch(notifyLogs);
        }
    }
    /**
     * 添加消息
     *
     * @param param      参数
     * @param content    消息内容
     * @param template   模板
     * @param isRead     阅读状态
     * @param value      发送类型
     * @param notifyLogs 消息集合
     * @param orderNumber 订单号
     */
    private void addNotifyLog(NotifyTemplateParam param, String content, NotifyTemplate template, Boolean isRead, Integer value, List<NotifyLog> notifyLogs,String orderNumber) {
        NotifyLog notifyLog = new NotifyLog();
        notifyLog.setCreateTime(new Date());
        notifyLog.setShopId(param.getShopId());
        // 如果大于则为店铺自行接收的消息
        if (param.getSendType() >= 100) {
            notifyLog.setRemindId(param.getShopId().toString());
        } else {
            notifyLog.setRemindId(param.getUserId());
        }
        notifyLog.setSendType(param.getSendType());
        notifyLog.setMessage(content);
        notifyLog.setNickName(param.getNickName());
        notifyLog.setUserMobile(param.getUserMobile());
        notifyLog.setRemindType(value);
        notifyLog.setTemplateId(template.getTemplateId());
        notifyLog.setStatus(isRead ? 1 : 0);
        notifyLog.setOrderNumber(Objects.isNull(param.getOrderNumber()) ? null : param.getOrderNumber());
        notifyLog.setParamContent(Json.toJsonString(param));
        notifyLog.setProdName(Objects.isNull(param.getProdName()) ? null : param.getProdName());
        notifyLog.setActivityName(Objects.isNull(param.getActivityName()) ? null : param.getActivityName());
        notifyLog.setBlogId(Objects.isNull(param.getBlogId()) ? null : param.getBlogId());
        notifyLog.setType(Objects.isNull(param.getType()) ? null : param.getType());
        notifyLog.setUserId(Objects.isNull(param.getFromUserId()) ? null : param.getFromUserId());
        notifyLogs.add(notifyLog);

    }


    private Map<String, String> getSmsParam(NotifyTemplateParam param) {
        Map<String, String> smsParam = new HashMap<>(20);
        smsParam.put("orderNumber", param.getOrderNumber());
        smsParam.put("shopName", param.getShopName());
        smsParam.put("prodName", param.getProdName());
        smsParam.put("activityName", param.getActivityName());
        if (StrUtil.isBlank(param.getNickName())) {
            smsParam.put("nickName", "用户");
        } else {
            smsParam.put("nickName", param.getNickName());
        }
        smsParam.put("levelName", param.getLevelName());
        smsParam.put("cancelTime", param.getCancelTime());
        smsParam.put("price", String.valueOf(param.getPrice()));
        smsParam.put("dvyFlowId", param.getDvyFlowId());
        smsParam.put("stationName", param.getStationName());
        smsParam.put("dvyName", param.getDvyName());
        smsParam.put("dvyTime", DateUtil.format(param.getDvyTime(), DatePattern.NORM_DATETIME_PATTERN));
        smsParam.put("day", String.valueOf(Constant.MAX_REFUND_APPLY_TIME));
        smsParam.put("hour", param.getHour().toString());
        smsParam.put("date", DateUtil.format(param.getDvyTime(), DatePattern.NORM_DATETIME_PATTERN));
        return smsParam;
    }
    private Map<String, String> getSmsParamPerson(NotifyTemplateParam param) {
        Map<String, String> smsParam = new HashMap<>(20);
        smsParam.put("userName", param.getFromUserName());
        smsParam.put("toTypeName",param.getToTypeName());
        smsParam.put("content",param.getContent());
        smsParam.put("title",param.getTitle());
        return smsParam;
    }

    /**
     * 短信内容替换
     *
     * @param maps 替换内容
     */
    private String replaceContent(Map<String, String> maps, String content) {
        log.info("点赞收藏举报动态驳回消息替换{},{}",Json.toJsonString(maps),content);
        for (Map.Entry<String, String> element : maps.entrySet()) {
            if (StrUtil.isNotBlank(element.getValue())) {
                content = content.replace("${" + element.getKey() + "}", element.getValue());
            }
        }
        return content;
    }

}
